﻿using System;
using System.Collections.Generic;
using CoreEx.Common.Proxy;
using LinFu.IoC.Configuration;
using LinFu.Proxy.Interfaces;
using Mono.Cecil;
using CoreEx.Common.Extensions;

namespace CoreEx.Common.Implementation.Proxy
{
    /// <summary>
    /// Modifies an <see cref="IProxy"/> type to include a static <see cref="IConstructorInterceptor"/> property.
    /// </summary>
    [Implements(typeof(ITypeModifier), ServiceName = "ConstructorInterceptorModifier")]
    public class ConstructorInterceptorModifier : ITypeModifier
    {
        /// <summary>
        /// Executes just before the proxy type has been constructed.
        /// </summary>
        /// <param name="originalBaseType">The base class from which the proxy is inherited.</param>
        /// <param name="baseInterfaces">The list of interfaces implemented by the proxy type.</param>
        /// <param name="module">The <see cref="ModuleDefinition"/> that will hold the brand new type.</param>        
        /// <param name="typeDefinition">The <see cref="TypeDefinition"/> that represents the created type.</param>
        public void BeforeConstruction(Type originalBaseType, IEnumerable<Type> baseInterfaces, ModuleDefinition module, TypeDefinition typeDefinition)
        {
            
        }

        /// <summary>
        /// Executes just after the proxy type has been constructed.
        /// </summary>
        /// <param name="originalBaseType">The base class from which the proxy is inherited.</param>
        /// <param name="baseInterfaces">The list of interfaces implemented by the proxy type.</param>
        /// <param name="module">The <see cref="ModuleDefinition"/> that will hold the brand new type.</param>
        /// <param name="typeDefinition">The <see cref="TypeDefinition"/> that represents the created type.</param>
        public void AfterConstruction(Type originalBaseType, IEnumerable<Type> baseInterfaces, ModuleDefinition module, TypeDefinition typeDefinition)
        {                        
            var constructorAroundInvokeType = module.Import(typeof(IConstructorInterceptor));
            typeDefinition.AddStaticProperty("ConstructorInterceptor", constructorAroundInvokeType);        
        }
    }
}
